﻿using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using BillsPresentation;
using BillsDomain;
using System.ComponentModel;
using Microsoft.Research.DynamicDataDisplay.DataSources;

[assembly: CLSCompliant(true)]
namespace BillsWpf
{
    /// <summary>
    /// Interaction logic for PaymentReminder.xaml
    /// </summary>
    public partial class PaymentReminder : Window, IPaymentReminderView
    {
        /// <summary>
        /// The form's presenter
        /// </summary>
        private PaymentReminderPresenter presenter;

        /// <summary>
        /// The form for adding and editing payments
        /// </summary>
        private AddPaymentWindow addPaymentWindow;

        /// <summary>
        /// Initializes a new instance of the <see cref="PaymentReminder"/> class.
        /// </summary>
        public PaymentReminder()
        {
            InitializeComponent();
            this.calendarItemsForADay.SelectedDate = DateTime.Today;
            this.datePickerDateForProjection.SelectedDate = DateTime.Today;
            presenter = new PaymentReminderPresenter(this, new ScheduledPaymentController());
        }

        /// <summary>
        /// Handles the Click event of the buttonAdd control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void buttonAdd_Click(object sender, RoutedEventArgs e)
        {
            if (this.addPaymentWindow == null)
            {
                this.addPaymentWindow = new AddPaymentWindow(this.presenter.Controller);
            }

            addPaymentWindow.AddMode = true;
            bool? result = this.addPaymentWindow.ShowDialog();
            this.addPaymentWindow = null;
        }

        /// <summary>
        /// Handles the Click event of the buttonEdit control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void buttonEdit_Click(object sender, RoutedEventArgs e)
        {
            if (this.addPaymentWindow == null)
            {
                this.addPaymentWindow = new AddPaymentWindow(this.presenter.Controller);
            }

            addPaymentWindow.AddMode = false;
            bool? result = this.addPaymentWindow.ShowDialog();
            this.addPaymentWindow = null;
        }

        /// <summary>
        /// Handles the Loaded event of the Window control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            if (this.Load != null)
            {
                this.Load(sender, e);
            }

            CollectionViewSource paymentWithDateViewSource = ((CollectionViewSource)(this.FindResource("paymentWithDateViewSource")));
            // Load data by setting the CollectionViewSource.Source property:
            // paymentWithDateViewSource.Source = [generic data source]
            CollectionViewSource paymentViewSource = ((CollectionViewSource)(this.FindResource("paymentViewSource")));
            // Load data by setting the CollectionViewSource.Source property:
            // paymentViewSource.Source = [generic data source]
            CollectionViewSource calendarDayViewSource = ((CollectionViewSource)(this.FindResource("calendarDayViewSource")));
            // Load data by setting the CollectionViewSource.Source property:
            // calendarDayViewSource.Source = [generic data source]
        }

        #region IPaymentReminderView Members

        /// <summary>
        /// Gets or sets the list of upcoming payments.
        /// </summary>
        /// <value>The upcoming payments.</value>
        public UpcomingPaymentsCollection UpcomingPayments
        {
            get { return ((CollectionViewSource)(this.FindResource("paymentWithDateViewSource"))).Source as UpcomingPaymentsCollection; }
            set
            {
                CollectionViewSource paymentWithDateViewSource = ((CollectionViewSource)(this.FindResource("paymentWithDateViewSource")));
                paymentWithDateViewSource.Source = value;
            }
        }

        /// <summary>
        /// Gets or sets the list of days and their balances.
        /// </summary>
        /// <value>The days and balances.</value>
        public BindingList<CalendarDay> DaysAndBalances
        {
            get
            {
                CollectionViewSource calendarDayViewSource = ((CollectionViewSource)(this.FindResource("calendarDayViewSource")));
                return calendarDayViewSource.Source as BindingList<CalendarDay>;
            }
            set
            {
                if (value != null)
                {
                    CollectionViewSource calendarDayViewSource = ((CollectionViewSource)(this.FindResource("calendarDayViewSource")));
                    calendarDayViewSource.Source = value;
                    DateTime[] dates = new DateTime[value.Count];
                    double[] balances = new double[value.Count];
                    int i = 0;
                    foreach (CalendarDay day in value)
                    {
                        dates[i] = day.Date.Date;
                        balances[i] = Decimal.ToDouble(day.EndOfDayBalance);
                        i++;
                    }

                    EnumerableDataSource<DateTime> dateSource = new EnumerableDataSource<DateTime>(dates);
                    dateSource.SetXMapping(x => dateAxis.ConvertToDouble(x));
                    EnumerableDataSource<double> balanceSource = new EnumerableDataSource<double>(balances);
                    balanceSource.SetYMapping(y => balanceAxis.ConvertToDouble(y));
                    CompositeDataSource allValues = new CompositeDataSource(dateSource, balanceSource);
                    balancesLineGraph.DataSource = allValues;
                    chartPlotterBalances.Viewport.FitToView();
                }
            }
        }

        /// <summary>
        /// Gets or sets the first date to consider when generating the upcoming payment list and the projected balance.
        /// </summary>
        /// <value>As of day.</value>
        public DateTime AsOfDay
        {
            get
            {
                return this.datePickerAsOfDate.SelectedDate.Value;
            }
            set
            {
                this.datePickerAsOfDate.SelectedDate = value;
            }
        }

        /// <summary>
        /// Gets or sets the day on calendar.
        /// </summary>
        /// <value>The day on calendar.</value>
        public DateTime DayOnCalendar
        {
            get { return this.calendarItemsForADay.SelectedDate ?? DateTime.Today; }
            set { throw new NotImplementedException(); }
        }

        /// <summary>
        /// Occurs when the as of date is changed.
        /// </summary>
        public event EventHandler AsOfDateChanged;

        /// <summary>
        /// Occurs when a scheduled payment is changed or added.
        /// </summary>
        public event EventHandler<ScheduledPaymentChangedEventArgs> ScheduledPaymentChanged;

        /// <summary>
        /// Occurs when the delete button is clicked.
        /// </summary>
        public event EventHandler DeleteClicked;

        /// <summary>
        /// Occurs when the an item used to calculate the projected balance is changed.
        /// </summary>
        public event EventHandler ProjectedBalanceItemsChanged;

        /// <summary>
        /// Gets the current balance.
        /// </summary>
        /// <value>The current balance.</value>
        public decimal? CurrentBalance
        {
            get
            {
                decimal? result;
                decimal nonNullResult;
                if (!decimal.TryParse(this.textBoxCurrentBalance.Text, out nonNullResult))
                {
                    result = null;
                }
                else
                {
                    result = nonNullResult;
                }

                return result;
            }
        }

        /// <summary>
        /// Gets or sets the projected balance.
        /// </summary>
        /// <value>The projected balance.</value>
        public string ProjectedBalance
        {
            get
            {
                return this.labelProjectedBalance.Content as string;
            }
            set
            {
                this.labelProjectedBalance.Content = value;
            }
        }

        /// <summary>
        /// Gets the date for balance projection.
        /// </summary>
        /// <value>The date for projection.</value>
        public DateTime DateForProjection
        {
            get { return this.datePickerDateForProjection.SelectedDate.Value; }
            set { this.datePickerDateForProjection.SelectedDate = value; }
        }

        #endregion

        #region IView Members

        /// <summary>
        /// Occurs when the window is loaded.
        /// </summary>
        public event EventHandler Load;

        /// <summary>
        /// Occurs when the window is closed.
        /// </summary>
        public event EventHandler FormClose;

        #endregion

        /// <summary>
        /// Handles the SelectedDateChanged event of the datePickerAsOfDate control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Controls.SelectionChangedEventArgs"/> instance containing the event data.</param>
        private void datePickerAsOfDate_SelectedDateChanged(object sender, SelectionChangedEventArgs e)
        {
            if (this.AsOfDateChanged != null)
            {
                this.AsOfDateChanged(sender, e);
            }
        }

        /// <summary>
        /// Handles the Closed event of the Window control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void Window_Closed(object sender, EventArgs e)
        {
            if (this.FormClose != null)
            {
                this.FormClose(sender, e);
            }
        }

        #region IPaymentReminderView Members


        /// <summary>
        /// Gets or sets the list of dates with payments.
        /// </summary>
        /// <value>The dates with payments.</value>
        public BindingList<CalendarDay> DatesWithPayments
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                if (value != null)
                {
                    List<DateTime> datesPayments = new List<DateTime>();
                    foreach (CalendarDay day in value)
                    {
                        datesPayments.Add(day.Date);
                    }

                    WeightConverter.BoldedDates = datesPayments;
                    /// Trigger redrawing of the calendar's days
                    this.calendarItemsForADay.DisplayDate = this.calendarItemsForADay.DisplayDate.AddMonths(1);
                    this.calendarItemsForADay.DisplayDate = this.calendarItemsForADay.DisplayDate.AddMonths(-1);
                }
            }
        }

        /// <summary>
        /// Occurs when a specific date on the calendar of days with payments is selected.
        /// </summary>
        public event EventHandler<DateSelectedEventArgs> SpecificDateSelected;

        /// <summary>
        /// Gets or sets the list of payments for a specific day.
        /// </summary>
        /// <value>The payments for A day.</value>
        public IList<Payment> PaymentsForADay
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                CollectionViewSource paymentViewSource = ((CollectionViewSource)(this.FindResource("paymentViewSource")));
                paymentViewSource.Source = value;
            }
        }

        #endregion

        /// <summary>
        /// Handles the SelectedDatesChanged event of the calendar1 control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Controls.SelectionChangedEventArgs"/> instance containing the event data.</param>
        private void calendar1_SelectedDatesChanged(object sender, SelectionChangedEventArgs e)
        {
            if (this.SpecificDateSelected != null && e.AddedItems.Count > 0)
            {
                this.SpecificDateSelected(this, new DateSelectedEventArgs() { SelectedDate = DateTime.Parse(e.AddedItems[0].ToString()) });
            }
        }

        /// <summary>
        /// Handles the TextChanged event of the textBoxCurrentBalance control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Controls.TextChangedEventArgs"/> instance containing the event data.</param>
        private void textBoxCurrentBalance_TextChanged(object sender, TextChangedEventArgs e)
        {
            if (this.ProjectedBalanceItemsChanged != null)
            {
                this.ProjectedBalanceItemsChanged(this, e);
            }
        }

        /// <summary>
        /// Handles the MouseDoubleClick event of the upcomingPaymentDataGrid control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Input.MouseButtonEventArgs"/> instance containing the event data.</param>
        private void upcomingPaymentDataGrid_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            PaymentWithDate selectedRow = this.upcomingPaymentDataGrid.SelectedCells[0].Item as PaymentWithDate;
            //BillsDataSet.UpcomingPaymentRow selectedUpcomingPaymentRow = selectedRow.Row as BillsDataSet.UpcomingPaymentRow;
            if (this.ScheduledPaymentChanged != null)
            {
                this.ScheduledPaymentChanged(sender, new ScheduledPaymentChangedEventArgs() { SelectedPayment = selectedRow });
            }

            if (addPaymentWindow == null)
            {
                addPaymentWindow = new AddPaymentWindow(this.presenter.Controller);
            }

            addPaymentWindow.AddMode = false;
            bool? result = this.addPaymentWindow.ShowDialog();
            this.addPaymentWindow = null;
        }

        /// <summary>
        /// Handles the Click event of the buttonDelete control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void buttonDelete_Click(object sender, RoutedEventArgs e)
        {
            PaymentWithDate r = this.upcomingPaymentDataGrid.SelectedCells[0].Item as PaymentWithDate;
            //BillsDataSet.UpcomingPaymentRow x = r.Row as BillsDataSet.UpcomingPaymentRow;
            if (this.ScheduledPaymentChanged != null)
            {
                this.ScheduledPaymentChanged(sender, new ScheduledPaymentChangedEventArgs() { SelectedPayment = r });
            }

            if (this.DeleteClicked != null)
            {
                this.DeleteClicked(sender, e);
            }
        }

        /// <summary>
        /// Handles the SelectedDateChanged event of the datePickerDateForProjection control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Controls.SelectionChangedEventArgs"/> instance containing the event data.</param>
        private void datePickerDateForProjection_SelectedDateChanged(object sender, SelectionChangedEventArgs e)
        {
            if (this.ProjectedBalanceItemsChanged != null)
            {
                this.ProjectedBalanceItemsChanged(this, e);
            }
        }


        public string PathToData
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        public string DataFileName
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        public event EventHandler DataExporting;

        public event EventHandler DataImporting;
    }
}
